package aliyun

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/swxctx/ghttp"
	"github.com/swxctx/xlog"
)

/*
	接口文档：https://help.aliyun.com/zh/dashscope/developer-reference/api-details?spm=a2c4g.11186623.0.0.e66d23edk4jpy6#b8ebf6b25eul6
*/

// Client API请求客户端
type Client struct {
	// 基础请求api
	baseUri string

	// API Key
	apiKey string

	// 是否调试模式[调试模式可以输出详细的信息]
	debug bool

	// 最大空消息数量
	maxEmptyMessageCount int
}

// NewClient 初始化请求客户端
func NewClient(apiKey string, debug ...bool) *Client{
	client := &Client{
		apiKey:               apiKey,
		baseUri:              "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
		maxEmptyMessageCount: 900,
	}
	if len(debug) > 0 {
		client.debug = debug[0]
	}

	if client.debug {
		xlog.SetLevel("debug")
	}

	return client
}

func MustNewClient(apiKey string, debug ...bool) *Client {
	client := NewClient(apiKey,debug...)
	return client
}

// SetMaxEmptyMessageCount 最大空消息数量
func (client *Client)SetMaxEmptyMessageCount(count int) {
	client.maxEmptyMessageCount = count
}

// SetDebug debug开关
func (client *Client)SetDebug(debug bool) {
	client.debug = debug
}

func (client *Client)GetApiKey()string{
	return client.apiKey
}

// Chat 对话接口
// func (client *Client)Chat(chatRequest *ChatRequest) (*ChatResponse, error) {
// 	return client.Chat(chatRequest)
// }

// // ChatStream 流式对话接口
// func (client *Client)ChatStream(chatRequest *ChatRequest) (*StreamReader, error) {
// 	return client.ChatStream(chatRequest)
// }

// Chat 对话方法
func (c *Client) Chat(chatRequest *ChatRequest) (*ChatResponse, error) {
	// new request
	req := ghttp.Request{
		Url:       c.baseUri,
		Method:    "POST",
		ShowDebug: c.debug,
		Body:      chatRequest,
	}
	req.AddHeader("Authorization", "Bearer "+c.apiKey)
	req.AddHeader("Content-Type", "application/json")

	// send request
	resp, err := req.Do()
	if err != nil {
		return nil, fmt.Errorf("ali: Chat err, err is-> %v", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("ali: Chat http response code not 200, code is -> %d", resp.StatusCode)
	}
	defer resp.Body.Close()

	// read body
	respBs, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("ali: Chat read resp body err-> %v", err)
	}
	if c.debug {
		xlog.Debugf("ali: chat resp-> %s", string(respBs))
	}

	// unmarshal data
	var (
		chatResp *ChatResponse
	)

	err = json.Unmarshal(respBs, &chatResp)
	if err != nil {
		return nil, fmt.Errorf("ali: Chat data unmarshal err-> %v", err)
	}
	return chatResp, nil
}

// ChatStream 流式对话方法
func (c *Client) ChatStream(chatRequest *ChatRequest) (*StreamReader, error) {
	// new request
	req := ghttp.Request{
		Url:       c.baseUri,
		Method:    "POST",
		ShowDebug: c.debug,
		Body:      chatRequest,
	}
	req.AddHeader("Authorization", "Bearer "+c.apiKey)
	req.AddHeader("Content-Type", "application/json")
	req.AddHeader("Accept", "text/event-stream")

	// send request
	resp, err := req.Do()
	if err != nil {
		return nil, fmt.Errorf("ali: Chat err, err is-> %v", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("ali: Chat http response code not 200, code is -> %d", resp.StatusCode)
	}

	// 交给外部调用逻辑处理
	return newStreamReader(resp, c.maxEmptyMessageCount), nil
}